package com.bestv.search.engine.servlet;

import com.bestv.search.common.cache.SystemCache;
import com.bestv.search.common.dao.SearchFieldInfoDao;
import com.bestv.search.engine.cache.KeySubjectFirstLevelCache;
import com.bestv.search.engine.command.LuceneSearchCommandRefactor;
import com.bestv.search.engine.compass.extend.HibernateGpsDeviceExtend;
import com.bestv.search.engine.compass.extend.SingleCompassGpsExtend;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.compass.core.Compass;
import org.dom4j.Document;
import org.dom4j.io.SAXReader;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author Michael Wang
 */

// $Id: VisSearchServlet.java 75 2012-03-19 11:38:39Z wbwang $
public final class VisSearchServlet extends HttpServlet {

    private static final long serialVersionUID = -8170585927249513816L;
    static Log slog = LogFactory.getLog("searchlog");
    static SimpleDateFormat timeformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    protected final Log log = LogFactory.getLog(getClass());
    private Compass compass;
    private LuceneSearchCommandRefactor luceneSearchCommand;
    private SingleCompassGpsExtend singleCompassGpsExtend;
    private SystemCache systemCache;

    public VisSearchServlet() {
        super();
    }

    @Override
    public void destroy() {
        log.info("destorying the VisSearchServlet!");
        super.destroy();
        LuceneSearchCommandRefactor.destory();
        singleCompassGpsExtend.stop();
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        try {
            String schCon = URLDecoder.decode(request.getParameter("q"), "UTF-8");
            slog.info(timeformat.format(new Date()) + "|" + request.getRemoteAddr() + "|" + schCon);
            String avatarRoot = request.getRequestURL().toString();
            // change to Avatar folder
            avatarRoot = avatarRoot.replace("/dosearch", "/avatar/");
            doExecute(schCon, response, avatarRoot);
        } catch (Exception e) {
            log.error("Parameter Error,please post param " + request.getParameter("q"));
            e.printStackTrace();
            response.getWriter().write("Parameter Error,please send param 'q'");
        }
    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        log.debug("doPost");
        try {
            response.setContentType("text/html;charset=UTF-8");
            slog.info(timeformat.format(new Date()) + "|" + request.getRemoteAddr() + "|" + request.getParameter("q"));
            String avatarRoot = request.getRequestURL().toString();
            // change to Avatar folder
            avatarRoot = avatarRoot.replace("/dosearch", "/avatar/");
            doExecute(request.getParameter("q"), response, avatarRoot);
        } catch (Exception e) {
            log.error("Parameter Error,please post param " + request.getParameter("q"));
            e.printStackTrace();
            response.getWriter().write("Parameter Error,please post param 'q'");
        }
    }

    @Override
    public void init() throws ServletException {
        super.init();
        ServletContext application = getServletContext();
        WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(application);
        compass = (Compass) wac.getBean("compass");
        systemCache = (SystemCache) wac.getBean("systemCache");
        SearchFieldInfoDao sfDao = (SearchFieldInfoDao) wac.getBean("searchFieldInfoDao");
        LuceneSearchCommandRefactor.initStaticFields(compass, sfDao);
        LuceneSearchCommandRefactor.setSpellCheckerIndexFolder(systemCache.getSpellCheckerIndex());
        KeySubjectFirstLevelCache.init();
        luceneSearchCommand = LuceneSearchCommandRefactor.getSingletonLuceneSearchCommand();
        luceneSearchCommand.setDefaultSortType(((HibernateGpsDeviceExtend) wac.getBean("gpsDevice")).getSortType());
        log.info("..sortType:" + luceneSearchCommand.getDefaultSortType());
        luceneSearchCommand.warm();

        // Start scheduleMirror for index
        singleCompassGpsExtend = (SingleCompassGpsExtend) wac.getBean("compassGps");
        singleCompassGpsExtend.start();
    }

    public void doExecute(String schCon, HttpServletResponse response, String avatarRoot) throws IOException {
        schCon = new String(schCon.getBytes("iso-8859-1"), "utf-8");
        log.debug("schCon:" + schCon);
        SAXReader reader = new SAXReader();
        Document doc = null;
        InputStream xmlInputStream = new ByteArrayInputStream(schCon.getBytes("UTF-8"));
        try {
            doc = reader.read(xmlInputStream);
        } catch (Exception e) {
            response.getWriter().write("Error!The Request Parameter cannot parse to XML");
            return;
        } finally {
            xmlInputStream.close();
        }
        String cmd = doc.selectSingleNode("/request/cmd").getText();
        String rsp = luceneSearchCommand.search(doc, cmd, avatarRoot);
        log.debug(">>>> rsp:\n" + rsp);
        response.getWriter().write(rsp);
        return;
    }

    public SystemCache getSystemCache() {
        return systemCache;
    }

    public void setSystemCache(SystemCache systemCache) {
        this.systemCache = systemCache;
    }
}
